package functor

import (
	"reflect"
)

// 函数封装接口
type CFunctorIF interface {
	Init(fc interface{}, params ...interface{})
	Call()
}

// 函数封装类
// 	备注：具体用法可以参考Util/timer/timer.go中的注释文档
type CFunctor struct {
	CFunctorIF
	fc            interface{}
	funcValRf     reflect.Value
	funcValRfList []reflect.Value
}

// 创建函数封装对象
func New(fc interface{}, params ...interface{}) interface{} {
	return new(CFunctor).Init(fc, params...)
}

// 创建函数封装对象2
func NewFuncPtr(fc interface{}) *CFunctor {
	return New(fc).(*CFunctor)
}

func (this *CFunctor) Init(fc interface{}, params ...interface{}) interface{} {
	//funcTypRf := reflect.TypeOf(fc)
	funcValRf := reflect.ValueOf(fc)
	// todo：对于多参数的情况，对于参数个数检查不太好检查，后续看其他方案
	//if len(params) < funcTypRf.NumIn() {
	//	errMsg := fmt.Sprintf("func:%s, params's num is invalid, %d <= %d",
	//		runtime.FuncForPC(funcValRf.Pointer()).Name(), len(params), funcTypRf.NumIn())
	//	tars.TLOG.Error(errMsg)
	//	return errors.WithStack(errors.New(errMsg))
	//}
	this.funcValRf = funcValRf
	//this.funcValRfList = make([]reflect.Value, funcTypRf.NumIn())
	this.funcValRfList = []reflect.Value{}
	for i := 0; i < len(params); i++ {
		tmpValRf := reflect.ValueOf(params[i])
		this.funcValRfList = append(this.funcValRfList, tmpValRf)
	}
	//for i := 0; i < funcTypRf.NumIn(); i++ {
	//	tmpValRf := reflect.ValueOf(params[i])
	//	this.funcValRfList[i] = tmpValRf
	//	// todo: fc参数类型检查，对于接口类型检查目前不太好做检查，后续看其他方案
	//}
	return this
}

// 执行预设参数
func (this *CFunctor) Call() {
	this.funcValRf.Call(this.funcValRfList)
}

// 执行实时传入参数 (这种调用方式不太建议，每次调用都需转换成反射参数)
func (this *CFunctor) CallByParams(params ...interface{}) bool {
	tmpRfParams := []reflect.Value{}
	for i := 0; i < len(params); i++ {
		tmpValRf := reflect.ValueOf(params[i])
		tmpRfParams = append(tmpRfParams, tmpValRf)
	}
	tmpReturns := this.funcValRf.Call(tmpRfParams)
	return tmpReturns[0].Bool()
}